import classNames from 'classnames';
import { format, getHours, getMinutes, setHours, setMinutes } from 'date-fns';
import { ChangeEvent, forwardRef, useContext, useEffect, useRef, useState } from 'react';
import { ThemeContext } from 'src/context/ThemeContext';
import Calendar from '../Calendar';
import style from './DatetimePicker.module.scss';
import Input from '../Input';

/**
 * usage exaple:
 *
 * <DatetimePicker
 *   label="label"
 *   className={style.picker}
 *   onChange={(v) => console.log(v.toISOString())}
 *   defaultDate={new Date('2022/03/20 10:20')}
 * />
 */

export type Props = {
  label?: string;
  error?: boolean | string;
  className?: string;
  onChange?: (date: string) => void;
  defaultValue?: Date;
  value?: string;
  clearable?: boolean;
};

const DatetimePicker = forwardRef<HTMLDivElement, Props>(
  ({ label, error, className, onChange, value, defaultValue, clearable = false }, ref) => {
    const dateRef = useRef<HTMLDivElement>(null);
    const [open, setOpen] = useState<boolean>(false);
    const [date, setDate] = useState<Date | undefined>(defaultValue);
    const [hour, setHour] = useState<string>(defaultValue ? String(getHours(defaultValue)) : '');
    const [minute, setMinute] = useState<string>(
      defaultValue ? String(getMinutes(defaultValue)) : '',
    );
    const { IcCalendar } = useContext(ThemeContext).image;

    useEffect(() => {
      if (date === undefined) onChange && onChange('');
      else {
        const datetime = setMinutes(setHours(date, Number(hour ?? 0)), Number(minute ?? 0));
        onChange && onChange(datetime.toISOString());
      }
    }, [date, hour, minute]);

    useEffect(() => {
      if (value) {
        const thisDate = new Date(value);
        setDate(thisDate);
        setHour(thisDate.getHours().toString());
        setMinute(thisDate.getMinutes().toString());
      } else {
        setDate(undefined);
        setHour('');
        setMinute('');
      }
    }, [value]);

    const onDateClick = (v: Date) => {
      setOpen(false);
      setDate(v);
    };

    const onHourChange = (e: ChangeEvent<HTMLInputElement>) => {
      setHour(e.target.value);
    };

    const onMinuteChange = (e: ChangeEvent<HTMLInputElement>) => {
      setMinute(e.target.value);
    };

    const onClear = () => {
      setOpen(false);
      setDate(undefined);
      setHour('');
      setMinute('');
    };

    return (
      <>
        <div className={classNames(style.self, className)}>
          {label && <div className={style.label}>{label}</div>}
          <div className={style.input} ref={ref}>
            <div
              className={classNames(style.date, { [style.error]: !!error })}
              ref={dateRef}
              onClick={() => setOpen(true)}
            >
              <img src={IcCalendar} />
              {date ? format(date, 'yyyy/MM/dd') : ''}
            </div>
            <div className={style.time}>
              <Input
                className={style.element}
                placeholder="00"
                regex={/^([01]{0,1}[0-9]{0,1}|2[0-3]{0,1})$/}
                onChange={onHourChange}
                value={hour}
                error={!!error}
              />
              <div>：</div>
              <Input
                className={style.element}
                placeholder="00"
                regex={/^[0-5]{0,1}[0-9]{0,1}$/}
                onChange={onMinuteChange}
                value={minute}
                error={!!error}
              />
            </div>
          </div>
        </div>
        <Calendar
          open={open}
          onClose={() => setOpen(false)}
          anchorEl={dateRef.current}
          value={date ?? new Date()}
          onChange={onDateClick}
          onClear={clearable ? onClear : undefined}
        />
      </>
    );
  },
);

DatetimePicker.displayName = 'DatetimePicker';

export default DatetimePicker;
